home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
rpg
/
crossfir.92
/
crossfir
/
crossfire-0.92.5
/
server
/
hiscore.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-24
|
10KB
|
323 lines
/*
* static char *rcsid_hiscore_c =
* "$Id: hiscore.c,v 1.13 1995/04/15 04:54:15 master Exp $";
*/
/*
CrossFire, A Multiplayer game for X-windows
Copyright (C) 1992 Frank Tore Johansen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author can be reached via e-mail to frankj@ifi.uio.no.
*/
#include <global.h>
#ifndef __CEXTRACT__
#include <sproto.h>
#endif
/*
* spool works mostly like strtok(char *, ":"), but it can also
* log a specified error message if something goes wrong.
*/
char *spool(char *bp,char *error) {
static char *prev_pos = NULL;
char *next_pos;
if (bp == NULL) {
if (prev_pos == NULL) {
LOG(llevError, "Called spool (%s) with NULL without previous call.\n",
error);
return NULL;
}
bp = prev_pos;
}
if (*bp == '\0') {
LOG(llevError, "spool: End of line at %s\n", error);
return NULL;
}
if ((next_pos = strchr(bp, ':')) != NULL) {
*next_pos = '\0';
prev_pos = next_pos + 1;
} else
prev_pos = NULL;
return bp;
}
/*
* Does what it says, copies the contents of the first score structure
* to the second one.
*/
void copy_score(score *sc1,score *sc2) {
strncpy(sc2->name, sc1->name, BIG_NAME);
sc2->name[BIG_NAME - 1] = '\0';
strncpy(sc2->killer, sc1->killer, BIG_NAME);
sc2->killer[BIG_NAME - 1] = '\0';
sc2->exp = sc1->exp;
strcpy(sc2->maplevel,sc1->maplevel);
sc2->maxhp = sc1->maxhp;
sc2->maxsp = sc1->maxsp;
}
/*
* Writes the given score structure to a static buffer, and returns
* a pointer to it.
*/
char *put_score(score *sc) {
static char buf[MAX_BUF];
sprintf(buf,"%s:%ld:%s:%s:%d:%d",sc->name,sc->exp,sc->killer,sc->maplevel,
sc->maxhp,sc->maxsp);
return buf;
}
/*
* The oposite of put_score, get_score reads from the given buffer into
* a static score structure, and returns a pointer to it.
*/
score *get_score(char *bp) {
static score sc;
char *cp;
if((cp=strchr(bp,'\n'))!=NULL)
*cp='\0';
if ((cp = spool(bp, "name")) == NULL)
return NULL;
strncpy(sc.name,cp,BIG_NAME);
sc.name[BIG_NAME - 1] = '\0';
if ((cp = spool(NULL, "score")) == NULL)
return NULL;
sscanf(cp,"%ld",&sc.exp);
if ((cp = spool(NULL, "killer")) == NULL)
return NULL;
strncpy(sc.killer, cp, BIG_NAME);
sc.killer[BIG_NAME - 1] = '\0';
if ((cp = spool(NULL, "map")) == NULL)
return NULL;
strncpy(sc.maplevel, cp, BIG_NAME);
sc.maplevel[BIG_NAME - 1] = '\0';
if ((cp = spool(NULL, "maxhp")) == NULL)
return NULL;
sscanf(cp, "%d", &sc.maxhp);
if ((cp = spool(NULL, "maxhp")) == NULL)
return NULL;
sscanf(cp, "%d", &sc.maxsp);
return ≻
}
/*
* add_score() adds the given score-structure to the high-score list, but
* only if it was good enough to deserve a place.
*/
score *add_score(score *new_score) {
FILE *fp;
static score old_score;
score *tmp_score,pscore[HIGHSCORE_LENGTH];
char buf[MAX_BUF], filename[MAX_BUF], *bp;
int nrofscores=0,flag=0,i,comp;
new_score->position=HIGHSCORE_LENGTH+1;
old_score.position= -1;
sprintf(filename,"%s/%s",LibDir,HIGHSCORE);
if((fp=open_and_uncompress(filename,1,&comp))!=NULL) {
while(fgets(buf,MAX_BUF,fp)!=NULL&&nrofscores<HIGHSCORE_LENGTH) {
if((tmp_score=get_score(buf))==NULL) break;
if(!flag&&new_score->exp>=tmp_score->exp) {
copy_score(new_score,&pscore[nrofscores]);
new_score->position=nrofscores;
flag=1;
if(++nrofscores>=HIGHSCORE_LENGTH)
break;
}
if(!strcmp(new_score->name,tmp_score->name)) { /* Another entry */
copy_score(tmp_score,&old_score);
old_score.position=nrofscores;
if(flag)
continue;
}
copy_score(tmp_score,&pscore[nrofscores++]);
}
close_and_delete(fp, comp);
}
if(old_score.position!=-1&&old_score.exp>=new_score->exp)
return &old_score; /* Did not beat old score */
if(!flag&&nrofscores<HIGHSCORE_LENGTH)
copy_score(new_score,&pscore[nrofscores++]);
if((fp=fopen(filename,"w"))==NULL) {
perror("Couldn't write to highscore-list.\n");
return NULL;
}
for(i=0;i<nrofscores;i++) {
bp=put_score(&pscore[i]);
fprintf(fp,"%s\n",bp);
}
fclose(fp);
if(flag) {
/* Eneq(@csd.uu.se): Patch to fix error in adding a new score to the
hiscore-list */
if(old_score.position==-1)
return new_score;
return &old_score;
}
new_score->position= -1;
if(old_score.position!=-1)
return &old_score;
if(nrofscores) {
copy_score(&pscore[nrofscores-1],&old_score);
return &old_score;
}
LOG(llevError,"Highscore error.\n");
return NULL;
}
void check_score(object *op) {
char buf[MAX_BUF];
score new_score;
score *old_score;
if(op->stats.exp==0)
return;
if(!op->contr->name_changed) {
if(op->stats.exp>0) {
new_draw_info(NDI_UNIQUE, 0,op,"As you haven't changed your name, you won't");
new_draw_info(NDI_UNIQUE, 0,op,"get into the high-score list.");
}
return;
}
if(QUERY_FLAG(op,FLAG_WAS_WIZ)) {
new_draw_info(NDI_UNIQUE, 0,op,"Since you have been in wizard mode,");
new_draw_info(NDI_UNIQUE, 0,op,"you can't enter the high-score list.");
return;
}
#ifdef EXPLORE_MODE
if (op->contr->explore) {
new_draw_info(NDI_UNIQUE, 0,op,"Since you were in explore mode,");
new_draw_info(NDI_UNIQUE, 0,op,"you can't enter the high-score list.");
return;
}
#endif
sprintf(buf,"%s the %s",op->name,op->contr->title);
strncpy(new_score.name,buf,BIG_NAME);
strncpy(new_score.killer,op->contr->killer,BIG_NAME);
if(new_score.killer[0]=='\0')
strcpy(new_score.killer,"a dungeon collapse");
new_score.exp=op->stats.exp;
if(op->map == NULL)
*new_score.maplevel = '\0';
else {
strncpy(new_score.maplevel,op->map->map_object->name,BIG_NAME-1);
new_score.maplevel[BIG_NAME-1] = '\0';
}
new_score.maxhp=(int) op->stats.maxhp;
new_score.maxsp=(int) op->stats.maxsp;
if((old_score=add_score(&new_score))==NULL) {
new_draw_info(NDI_UNIQUE, 0,op,"Error in the highscore list.");
return;
}
if(new_score.position == -1) {
new_score.position = HIGHSCORE_LENGTH+1; /* Not strictly correct... */
if(!strcmp(old_score->name,new_score.name))
new_draw_info(NDI_UNIQUE, 0,op,"You didn't beat your last highscore:");
else
new_draw_info(NDI_UNIQUE, 0,op,"You didn't enter the highscore list:");
draw_one_high_score(old_score);
new_draw_info(NDI_UNIQUE, 0,op,errmsg);
draw_one_high_score(&new_score);
new_draw_info(NDI_UNIQUE, 0,op,errmsg);
return;
}
if(old_score->exp>=new_score.exp)
new_draw_info(NDI_UNIQUE, 0,op,"You didn't beat your last score:");
else
new_draw_info(NDI_UNIQUE, 0,op,"You beat your last score:");
draw_one_high_score(old_score);
new_draw_info(NDI_UNIQUE, 0,op,errmsg);
draw_one_high_score(&new_score);
new_draw_info(NDI_UNIQUE, 0,op,errmsg);
}
void draw_one_high_score(score *sc) {
if(!strncmp(sc->killer,"quit",MAX_NAME))
sprintf(errmsg,"%3d %10ld %s quit the game on map %s [%d][%d].",
sc->position,sc->exp,sc->name,sc->maplevel,sc->maxhp,sc->maxsp);
else if(!strncmp(sc->killer,"left",MAX_NAME))
sprintf(errmsg,"%3d %10ld %s left the game on map %s [%d][%d].",
sc->position,sc->exp,sc->name,sc->maplevel,sc->maxhp,sc->maxsp);
else
sprintf(errmsg,"%3d %10ld %s was killed by %s on map %s [%d][%d].",
sc->position,sc->exp,sc->name,sc->killer,sc->maplevel,
sc->maxhp,sc->maxsp);
}
void display_high_score(object *op,int max) {
FILE *fp;
char buf[MAX_BUF],buf2[MAX_BUF], filename[MAX_BUF], *bp;
int i=0,j=0,maxchar=(op==NULL?80:INFOCHARS),comp;
score *sc;
sprintf(filename,"%s/highscore",LibDir);
if((fp=open_and_uncompress(filename,0,&comp))==NULL) {
perror("Couldn't open highscore file");
if(op!=NULL)
new_draw_info(NDI_UNIQUE, 0,op,"There is no highscore file.");
return;
}
sprintf(buf,"Nr Score Who [max hitpoints][max spellpoints]");
if(op==NULL && active_socket == (sockets *) NULL)
printf("%s\n",buf);
else {
if(op != NULL)
clear_win_info(op);
new_draw_info(NDI_UNIQUE, 0,op,buf);
}
while(fgets(buf,MAX_BUF,fp)!=NULL) {
if(j>=HIGHSCORE_LENGTH||i>=(max-1))
break;
if((sc=get_score(buf))==NULL)
break;
i++,j++;
sc->position=j;
draw_one_high_score(sc);
strncpy(buf,errmsg,MAX_BUF);
bp=buf+maxchar;
if((int)strlen(buf) > maxchar)
while(*bp!=' '&&bp>buf)
bp--;
strncpy(buf2,buf,bp-buf);
buf2[bp-buf]='\0';
if (op == NULL && active_socket == (sockets *) NULL)
printf("%s\n",buf2);
else
new_draw_info(NDI_UNIQUE, 0,op,buf2);
if((int)strlen(buf) > maxchar) {
i++;
strcpy(buf2," ");
strcat(buf2,bp);
if(op == NULL && active_socket == (sockets *) NULL)
printf("%s\n",buf2);
else
new_draw_info(NDI_UNIQUE, 0,op,buf2);
}
}
close_and_delete(fp, comp);
}